package cn.iocoder.yudao.module.dify.util;

import cn.iocoder.yudao.module.dify.api.vo.resp.ResponseData;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.markdown.MarkdownRenderData;
import com.deepoove.poi.plugin.markdown.MarkdownRenderPolicy;
import com.deepoove.poi.plugin.markdown.MarkdownStyle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import reactor.core.publisher.Flux;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class MarkdownToWordUtil {

    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 把一个文件转成 Flux<ResponseData>
     *
     * <pre>
     *     Flux<ResponseData> responseDataFlux = MarkdownToWordUtil.parseResponseDataFlux(inputStream);
     *
     * data:{"event":"message","conversation_id":"0dbbfacd-4c6f-4fa1-9811-49983ca30735","message_id":"ab11f39b-f9a3-4c35-9a5b-1cc0ae45d864","answer":"测","from_variable_selector":["1745050241222","text"]}
     * data:{"event":"message","conversation_id":"0dbbfacd-4c6f-4fa1-9811-49983ca30735","message_id":"ab11f39b-f9a3-4c35-9a5b-1cc0ae45d864","answer":"体温","from_variable_selector":["1745050241222","text"]}
     * 转成 Flux<ResponseData>
     * </pre>
     *
     * @param inputStream
     * @return
     */
    public static Flux<ResponseData> parseResponseDataFlux(InputStream inputStream) {
        return Flux.using(
                () -> new BufferedReader(new InputStreamReader(inputStream)),
                reader -> Flux.create(sink -> {
                    try {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            if (line.trim().startsWith("data:")) {
                                String json = line.trim().substring(5);
                                try {
                                    ResponseData data = mapper.readValue(json, ResponseData.class);
                                    if (Objects.isNull(data)) {
                                        continue;
                                    }
                                    sink.next(data);
                                } catch (Exception e) {
                                    // 忽略无法解析的 JSON 数据
                                }
                            }
                        }
                        sink.complete();
                    } catch (IOException e) {
                        sink.error(e);
                    }
                }),
                reader -> {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        // 可记录日志或忽略
                    }
                }
        );
    }

    /**
     * Flux<ResponseData> responseDataFlux 中的 answer 拼接成 markdown 文件
     *
     * @param responseDataFlux
     * @return
     */
    public static void writeMarkdownFile(Flux<ResponseData> responseDataFlux) {
        responseDataFlux.map(data -> data.getAnswer() == null ? "" : data.getAnswer()) // 提取每个 ResponseData 的 answer
                .reduce(new StringBuilder(), (sb, answer) -> sb.append(answer)) // 拼接
                .map(StringBuilder::toString)
                .subscribe(result -> {
                    try (FileWriter writer = new FileWriter("Answers.md")) {
                        writer.write(result);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
    }

    /**
     * Flux<ResponseData> responseDataFlux 中的 answer 拼接成 String
     *
     * @param responseDataFlux
     * @return
     */
    public static StringBuilder writeMarkdownString(Flux<ResponseData> responseDataFlux) {
        return responseDataFlux
                .map(data -> data.getAnswer() == null ? "" : data.getAnswer())
                .reduce(new StringBuilder(), (sb, answer) -> sb.append(answer))
                .block(); // 等待处理完成并获取最终字符串


    }

    /**
     * markdown 文件转成 word 文件
     *
     * @param markdownFilePath
     * @param outputDocxPath
     * @throws Exception
     */
    public static void markdownFileToWordFile(String markdownFilePath, String outputDocxPath) throws Exception {
        // 1. 读取 Markdown 文件
        String markdownContent = new String(java.nio.file.Files.readAllBytes(new File(markdownFilePath).toPath()));

        // 2. 使用 Flexmark 将 Markdown 转换为 HTML
        com.vladsch.flexmark.html.HtmlRenderer renderer = com.vladsch.flexmark.html.HtmlRenderer.builder().build();
        com.vladsch.flexmark.parser.Parser parser = com.vladsch.flexmark.parser.Parser.builder().build();
        String htmlContent = renderer.render(parser.parse(markdownContent));

        // ✅ 替换 <br> 为 <br/>
        htmlContent = htmlContent.replaceAll("<br\\s*/?>", "<br/>");

        // 3. 创建 Word 文档并导入 HTML
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
        MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

        // ✅ 使用 XHTMLImporter 导入 HTML 内容
        XHTMLImporterImpl xhtmlImporter = new XHTMLImporterImpl(wordMLPackage);
        String validHtml = "<html><body>" + htmlContent + "</body></html>";
        List<Object> contentElements = xhtmlImporter.convert(validHtml, null);

        // ✅ 添加到文档主体
        mainDocumentPart.getContent().addAll(contentElements);

        // 4. 保存文件
        try (FileOutputStream out = new FileOutputStream(outputDocxPath)) {
            wordMLPackage.save(out);
        }
    }

    /**
     * markdown 字符串转成 word 文件 使用poi-tl 对表格友好
     *
     * @param markdownContent
     * @param outputDocxPath
     * @throws Exception
     */
    public static void markdownStringToWordFilePoiTl(String markdownContent, String outputDocxPath) throws Exception {
        MarkdownRenderData code = new MarkdownRenderData();
//        byte[] bytes = Files.readAllBytes(Paths.get("Answers33.md"));
//        String mkdn = new String(bytes);
        markdownContent = MarkdownToWordUtil.processArrangeMarkdown(markdownContent);
        markdownContent = markdownContent.replace("<br>", "");
        code.setMarkdown(markdownContent);
        MarkdownStyle style = MarkdownStyle.newStyle();
//        style.setImagesDir("/Users/sai/Sayi/blog/");
        style.setShowHeaderNumber(false);
        code.setStyle(style);
//        TextRenderData textRenderData = new TextRenderData();
//        Style style = textRenderData.getStyle();
//        style.setFontFamily("微软雅黑");
//        style.setFontSize("");
        Map<String, Object> data = new HashMap<>();
        data.put("md", code);
//        FileMarkdownRenderData fileMarkdownRenderData = new FileMarkdownRenderData();
//        fileMarkdownRenderData.setPath("src/test/resources/markdown/basic.md");
//        fileMarkdownRenderData.setStyle(style);
//        data.put("md", fileMarkdownRenderData);

        Configure config = Configure.builder().bind("md", new MarkdownRenderPolicy()).build();
        //获得文档模板
//        File file = ResourceUtils.getFile("classpath:markdown/markdown_template.docx");
//        String absolutePath = file.getAbsolutePath();
        // 使用 ClassLoader 获取模板文件的 InputStream
        try (InputStream templateStream = MarkdownToWordUtil.class.getClassLoader().getResourceAsStream("markdown/markdown_template.docx")) {
            if (templateStream == null) {
                throw new FileNotFoundException("Template file not found in classpath: markdown/markdown_template.docx");
            }

            XWPFTemplate.compile(templateStream, config)
                    .render(data)
                    .writeToFile(outputDocxPath);
        }

    }

    /**
     * 处理 markdown 中表格的格式方便转换
     *
     * @param markdown
     * @return
     */
    public static String processArrangeMarkdown(String markdown) {
        String[] lines = markdown.split("\\n");
        StringBuilder processed = new StringBuilder();
        boolean previousLineEndsWithBar = false;
        for (String line : lines) {
            String trimmedLine = line.trim();
            boolean currentLineIsTable = trimmedLine.startsWith("|") && trimmedLine.endsWith("|");
            if (currentLineIsTable && !previousLineEndsWithBar && !trimmedLine.equals("|---|")) {
                // 当前行是表格行，且上一行不是表格行，则插入空行
                processed.append("\r\n"); // 插入空行
            }
            processed.append(line).append("\n");
            // 更新“上一行是否以 | 结尾”状态
            previousLineEndsWithBar = trimmedLine.endsWith("|");
        }
        return processed.toString();
    }

    public static void markdownStringToWordFile(String markdownContent, String outputDocxPath) throws Exception {
        // 2. 使用 Flexmark 将 Markdown 转换为 HTML
        com.vladsch.flexmark.html.HtmlRenderer renderer = com.vladsch.flexmark.html.HtmlRenderer.builder().build();
        com.vladsch.flexmark.parser.Parser parser = com.vladsch.flexmark.parser.Parser.builder().build();
        String htmlContent = renderer.render(parser.parse(markdownContent));
        // ✅ 替换 <br> 为 <br/>
        htmlContent = htmlContent.replaceAll("<br\\s*/?>", "<br/>");
        // 3. 创建 Word 文档并导入 HTML
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
        MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();
        // ✅ 使用 XHTMLImporter 导入 HTML 内容
        XHTMLImporterImpl xhtmlImporter = new XHTMLImporterImpl(wordMLPackage);
        String validHtml = "<html><body>" + htmlContent + "</body></html>";
        List<Object> contentElements = xhtmlImporter.convert(validHtml, null);

        // ✅ 添加到文档主体
        mainDocumentPart.getContent().addAll(contentElements);

        // 4. 保存文件
        try (FileOutputStream out = new FileOutputStream(outputDocxPath)) {
            wordMLPackage.save(out);
        }
    }

}
